package com.ifp.opengate.boot.decode;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import com.alibaba.fastjson.JSON;
import com.ifp.core.util.StringUtil;
import com.ifp.opengate.boot.bean.ValidatorForm;
import com.ifp.opengate.boot.emum.ErrorEnum;
import com.ifp.opengate.boot.exception.AccessControlException;
import com.ifp.opengate.boot.utils.DecodeToolDelegate;
import com.ifp.opengate.boot.validator.ValidatorTool;

import net.sf.json.JSONArray;
import net.sf.json.JSONObject;

/**
 * <p>
 * 报文适配器
 * </P>
 *
 * @author zhuzh@belink.com
 * @version 0.0.1
 * @className MessageAdapter
 * @sine 2020/4/24 14:25
 */
@Component
public final class RequestMessageTool {

    @Autowired
    ValidatorTool validatorTool;

    public Map<String, Object> packRequestMessage(String cipher, List<ValidatorForm> validatorFormList,
        JSONObject jsonObject) throws Exception {
        Map<String, Object> requestMap = new HashMap<>();
        List<ValidatorForm> requestFormList = validatorFormList.stream()
            .filter(validatorForm -> "0".equals(validatorForm.getParamDirection())).collect(Collectors.toList());
        int size = requestFormList.size();
        for (int i = 0; i < size; i++) {
            this.dealwithRequestForm(cipher, requestFormList.get(i), requestMap, jsonObject);
        }
        return requestMap;
    }

    /**
     * 请求报文 验证 映射 加密
     * 
     * @param cipher
     * @param validatorForm
     * @param container
     * @param fromObject
     * @throws Exception
     */
    private void dealwithRequestForm(String cipher, ValidatorForm validatorForm, Map<String, Object> container,
        JSONObject fromObject) throws Exception {
        // ParamType 0字段 1集合 2对象（Map）3 数组
        if ("0".equals(validatorForm.getParamType())) {
            // String
            String o = (String)getFieldValue(validatorForm, fromObject);
            dealWithField(cipher, container, validatorForm, o);
        } else if ("2".equals(validatorForm.getParamType())) {
            // JSONObject
            Object tmpObj = getFieldValue(validatorForm, fromObject);
            Map<String, Object> map = new HashMap<>();
            if (tmpObj == null) {
                container.put(validatorForm.getParamName(), map);
            } else {
                JSONObject jsonObj = (JSONObject)tmpObj;
                dealwithMap(cipher, validatorForm, map, jsonObj);
                container.put(validatorForm.getParamName(), map);
            }
        } else if ("3".equals(validatorForm.getParamType())) {
            JSONArray obj = (JSONArray)getFieldValue(validatorForm, fromObject);
            if (obj == null) {
                if (!"O".equals(validatorForm.getIsNeed())) {
                    container.put(validatorForm.getParamName(), new Object[] {});
                }
            } else {
                container.put(validatorForm.getParamName(), obj.toArray());
            }
        } else {
            String key = StringUtil.hasText(validatorForm.getParamMappingKey()) ? validatorForm.getParamMappingKey()
                : validatorForm.getParamName();
            // 加密处理，需要解密
            if ("1".equals(validatorForm.getIsEncode())) {
                String o = null;
                Object object = getFieldValue(validatorForm, fromObject);
                if (object instanceof String) {
                    o = (String)object;
                } else {
                    throw new AccessControlException(ErrorEnum.isNotString.code(),
                        String.format(ErrorEnum.isNotString.msg(), validatorForm.getParamName()));
                }
                if (!StringUtil.hasText(o)) {
                    throw new AccessControlException(ErrorEnum.decodeError.code(),
                        String.format(ErrorEnum.decodeError.msg(), validatorForm.getParamName()));
                }
                List<Map> decode = (List<Map>)DecodeToolDelegate.decode(cipher, o, validatorForm);
                JSONArray fieldValue = JSONArray.fromObject(decode);
                List<Map<String, Object>> mapList = new ArrayList<>();
                dealwithList(cipher, validatorForm, mapList, fieldValue);
                container.put(key, mapList);
            } else {
                JSONArray fieldValue = (JSONArray)getFieldValue(validatorForm, fromObject);
                List<Map<String, Object>> mapList = new ArrayList<>();
                dealwithList(cipher, validatorForm, mapList, fieldValue);
                container.put(key, mapList);
            }
        }
    }

    private void dealwithMap(String cipher, ValidatorForm validatorForm, Map<String, Object> map, JSONObject jsonObj)
        throws Exception {
        if (null == jsonObj) {
            return;
        }
        List<ValidatorForm> formList = validatorForm.getFormList();

        for (int i = 0; i < formList.size(); i++) {
            ValidatorForm form = formList.get(i);
            dealwithRequestForm(cipher, form, map, jsonObj);
        }
    }

    /**
     * 处理field值
     *
     * @param cipher
     * @param container
     * @param validatorForm
     * @param o
     * @throws Exception
     */
    private void dealWithField(String cipher, Map<String, Object> container, ValidatorForm validatorForm, String o)
        throws Exception {
        if ("1".equals(validatorForm.getIsEncode())) {
            // 获取上送值
            if (!StringUtil.hasText(o)) {
                throw new AccessControlException(ErrorEnum.decodeError.code(),
                    String.format(ErrorEnum.decodeError.msg(), validatorForm.getParamName()));
            }
            String decode = (String)DecodeToolDelegate.decode(cipher, o, validatorForm);
            mapperKey(validatorForm, container, decode);
        } else {
            // 获取上送值 todo 参数检查还没有实现先不做
            mapperKey(validatorForm, container, o);
        }
    }

    /**
     * 通过加密
     *
     * @param validatorForm
     * @param jsonObject
     * @return
     */
    private Object getFieldValue(ValidatorForm validatorForm, JSONObject jsonObject) {
        Object object = null;
        if ("1".equals(validatorForm.getIsEncode())) {
            object = jsonObject.get(validatorForm.getEncodeMappingKey());
            if (!StringUtil.hasText(object)) {
                object = jsonObject.get(validatorForm.getParamName());
            }

            if (!StringUtil.hasText(object)) {
                if ("1".equals(validatorForm.getParamType())) {
                    object = new JSONArray();
                }
            }
            return object;
        } else {
            return jsonObject.get(validatorForm.getParamName());
        }
    }

    /**
     * 参数映射
     *
     * @param validatorForm
     * @param container
     * @param decode
     */
    private void mapperKey(ValidatorForm validatorForm, Map<String, Object> container, String decode)
        throws IllegalAccessException {
        validatorTool.validator(validatorForm, decode);
        // 当映射参数不为空时候有映射值
        if ("O".equals(validatorForm.getIsNeed()) && StringUtils.isBlank(decode)) {
            // O是可选参数，如果合作方没有送可选参数则网关也不送到服务系统
            return;
        }
        if (StringUtil.hasText(validatorForm.getParamMappingKey())) {
            if (validatorForm.getParamMappingKey().contains("||")) {
                String[] mapkeys = validatorForm.getParamMappingKey().split("\\|\\|", -1);
                for (int i = 0; i < mapkeys.length; i++) {
                    if (StringUtils.isBlank(mapkeys[i])) {
                        continue;
                    }
                    container.put(mapkeys[i], decode);
                }
            } else {
                container.put(validatorForm.getParamMappingKey(), decode);
            }
        } else {
            container.put(validatorForm.getParamName(), decode);
        }
    }

    /**
     * 处理参数List
     *
     * @param cipher
     * @param validatorForm
     * @param mapList
     * @param fieldValue
     * @throws Exception
     */
    private void dealwithList(String cipher, ValidatorForm validatorForm, List<Map<String, Object>> mapList,
        JSONArray fieldValue) throws Exception {
        if (null == fieldValue) {
            return;
        }
        List<ValidatorForm> formList = validatorForm.getFormList();
        int size = fieldValue.size();
        for (int j = 0; j < size; j++) {
            Map<String, Object> map = new HashMap<>();
            for (int i = 0; i < formList.size(); i++) {
                ValidatorForm form = formList.get(i);
                JSONObject jsonObject = fieldValue.getJSONObject(j);
                dealwithRequestForm(cipher, form, map, jsonObject);
            }
            mapList.add(map);
        }
    }

    public List<ValidatorForm> getValidatorList() {
        // 假数据
        // String s = "[\n" +
        // " {\n" +
        // " \"paramMappingKey\":\"custName\",\n" +
        // " \"paramOrder\":\"1\",\n" +
        // " \"paramParentId\":\"\",\n" +
        // " \"paramCName\":\"用户名称\",\n" +
        // " \"paramPosition\":\"0\",\n" +
        // " \"paramName\":\"username\",\n" +
        // " \"paramEncode\":\"\",\n" +
        // " \"paramIndex\":\"0\",\n" +
        // " \"paramType\":\"0\",\n" +
        // " \"paramDesc\":\"用户名称\",\n" +
        // " \"paramLength\":\"20\",\n" +
        // " \"paramIsCheck\":\"1\",\n" +
        // " \"paramDirection\":\"0\",\n" +
        // " \"paramValueType\":\"String\",\n" +
        // " \"paramId\":\"\",\n" +
        // " \"serviceId\":\"\",\n" +
        // " \"paramValue\":\"\",\n" +
        // " \"isEncode\":\"0\",\n" +
        // " \"checkRule\":\"NotEmpty\",\n" +
        // " \"checkPattern\":\"\",\n" +
        // " \"encodeMappingKey\":\"\"\n" +
        // " },\n" +
        // " {\n" +
        // " \"paramMappingKey\":\"userList\",\n" +
        // " \"paramOrder\":\"2\",\n" +
        // " \"paramParentId\":\"\",\n" +
        // " \"paramCName\":\"用户组\",\n" +
        // " \"paramPosition\":\"0\",\n" +
        // " \"paramName\":\"userList\",\n" +
        // " \"paramEncode\":\"\",\n" +
        // " \"paramIndex\":\"1\",\n" +
        // " \"paramType\":\"1\",\n" +
        // " \"paramDesc\":\"用户组\",\n" +
        // " \"paramLength\":\"\",\n" +
        // " \"paramIsCheck\":\"1\",\n" +
        // " \"paramDirection\":\"0\",\n" +
        // " \"paramValueType\":\"List\",\n" +
        // " \"paramId\":\"\",\n" +
        // " \"serviceId\":\"\",\n" +
        // " \"paramValue\":\"\",\n" +
        // " \"isEncode\":\"0\",\n" +
        // " \"checkRule\":\"NotEmpty\",\n" +
        // " \"checkPattern\":\"\",\n" +
        // " \"encodeMappingKey\":\"userEncodeList\",\n" +
        // " \"formList\":[\n" +
        // " {\n" +
        // " \"paramMappingKey\":\"user1\",\n" +
        // " \"paramOrder\":\"2.1\",\n" +
        // " \"paramParentId\":\"2\",\n" +
        // " \"paramCName\":\"用户1\",\n" +
        // " \"paramPosition\":\"0\",\n" +
        // " \"paramName\":\"user1\",\n" +
        // " \"paramEncode\":\"\",\n" +
        // " \"paramIndex\":\"2\",\n" +
        // " \"paramType\":\"0\",\n" +
        // " \"paramDesc\":\"用户\",\n" +
        // " \"paramLength\":\"20\",\n" +
        // " \"paramIsCheck\":\"0\",\n" +
        // " \"paramDirection\":\"0\",\n" +
        // " \"paramValueType\":\"String\",\n" +
        // " \"paramId\":\"\",\n" +
        // " \"serviceId\":\"\",\n" +
        // " \"paramValue\":\"\",\n" +
        // " \"isEncode\":\"0\",\n" +
        // " \"checkRule\":\"\",\n" +
        // " \"checkPattern\":\"\",\n" +
        // " \"encodeMappingKey\":\"\"\n" +
        // " },\n" +
        // " {\n" +
        // " \"paramMappingKey\":\"age\",\n" +
        // " \"paramOrder\":\"2.2\",\n" +
        // " \"paramParentId\":\"2\",\n" +
        // " \"paramCName\":\"年龄\",\n" +
        // " \"paramPosition\":\"0\",\n" +
        // " \"paramName\":\"age\",\n" +
        // " \"paramEncode\":\"\",\n" +
        // " \"paramIndex\":\"3\",\n" +
        // " \"paramType\":\"0\",\n" +
        // " \"paramDesc\":\"年龄\",\n" +
        // " \"paramLength\":\"3\",\n" +
        // " \"paramIsCheck\":\"0\",\n" +
        // " \"paramDirection\":\"0\",\n" +
        // " \"paramValueType\":\"int\",\n" +
        // " \"paramId\":\"\",\n" +
        // " \"serviceId\":\"\",\n" +
        // " \"paramValue\":\"\",\n" +
        // " \"isEncode\":\"0\",\n" +
        // " \"checkRule\":\"\",\n" +
        // " \"checkPattern\":\"\",\n" +
        // " \"encodeMappingKey\":\"\"\n" +
        // " }\n" +
        // " ]\n" +
        // " },\n" +
        // " {\n" +
        // " \"paramMappingKey\":\"userOutList\",\n" +
        // " \"paramOrder\":\"1\",\n" +
        // " \"paramParentId\":\"\",\n" +
        // " \"paramCName\":\"用户组\",\n" +
        // " \"paramPosition\":\"0\",\n" +
        // " \"paramName\":\"userOutList\",\n" +
        // " \"paramEncode\":\"\",\n" +
        // " \"paramIndex\":\"4\",\n" +
        // " \"paramType\":\"1\",\n" +
        // " \"paramDesc\":\"用户组\",\n" +
        // " \"paramLength\":\"\",\n" +
        // " \"paramIsCheck\":\"1\",\n" +
        // " \"paramDirection\":\"1\",\n" +
        // " \"paramValueType\":\"List\",\n" +
        // " \"paramId\":\"\",\n" +
        // " \"serviceId\":\"\",\n" +
        // " \"paramValue\":\"\",\n" +
        // " \"isEncode\":\"0\",\n" +
        // " \"checkRule\":\"NotEmpty\",\n" +
        // " \"checkPattern\":\"\",\n" +
        // " \"encodeMappingKey\":\"userOutEncodeList\",\n" +
        // " \"formList\":[\n" +
        // " {\n" +
        // " \"paramMappingKey\":\"\",\n" +
        // " \"paramOrder\":\"1.1\",\n" +
        // " \"paramParentId\":\"1\",\n" +
        // " \"paramCName\":\"用户\",\n" +
        // " \"paramPosition\":\"0\",\n" +
        // " \"paramName\":\"userOut\",\n" +
        // " \"paramEncode\":\"\",\n" +
        // " \"paramIndex\":\"5\",\n" +
        // " \"paramType\":\"0\",\n" +
        // " \"paramDesc\":\"\",\n" +
        // " \"paramLength\":\"\",\n" +
        // " \"paramIsCheck\":\"0\",\n" +
        // " \"paramDirection\":\"1\",\n" +
        // " \"paramValueType\":\"String\",\n" +
        // " \"paramId\":\"\",\n" +
        // " \"serviceId\":\"\",\n" +
        // " \"paramValue\":\"\",\n" +
        // " \"isEncode\":\"0\",\n" +
        // " \"checkRule\":\"\",\n" +
        // " \"checkPattern\":\"\",\n" +
        // " \"encodeMappingKey\":\"\"\n" +
        // " },\n" +
        // " {\n" +
        // " \"paramMappingKey\":\"\",\n" +
        // " \"paramOrder\":\"2\",\n" +
        // " \"paramParentId\":\"\",\n" +
        // " \"paramCName\":\"标志\",\n" +
        // " \"paramPosition\":\"0\",\n" +
        // " \"paramName\":\"flag\",\n" +
        // " \"paramEncode\":\"\",\n" +
        // " \"paramIndex\":\"6\",\n" +
        // " \"paramType\":\"0\",\n" +
        // " \"paramDesc\":\"标志\",\n" +
        // " \"paramLength\":\"\",\n" +
        // " \"paramIsCheck\":\"0\",\n" +
        // " \"paramDirection\":\"1\",\n" +
        // " \"paramValueType\":\"String\",\n" +
        // " \"paramId\":\"\",\n" +
        // " \"serviceId\":\"\",\n" +
        // " \"paramValue\":\"\",\n" +
        // " \"isEncode\":\"0\",\n" +
        // " \"checkRule\":\"\",\n" +
        // " \"checkPattern\":\"\",\n" +
        // " \"encodeMappingKey\":\"\"\n" +
        // " }\n" +
        // " ]\n" +
        // " }\n" +
        // "]";

        String s = "[\n" + "    {\n" + "        \"paramMappingKey\":\"\",\n" + "        \"paramOrder\":\"1\",\n"
            + "        \"isEncode\":\"0\",\n" + "        \"paramParentId\":\"\",\n"
            + "        \"checkRule\":\"NotEmpty\",\n" + "        \"paramCName\":\"用户\",\n"
            + "        \"paramPosition\":\"0\",\n" + "        \"paramName\":\"userNo\",\n"
            + "        \"paramEncode\":\"1\",\n" + "        \"paramIndex\":\"\",\n" + "        \"paramType\":\"0\",\n"
            + "        \"paramDesc\":\"\",\n" + "        \"encodeMappingKey\":\"\",\n"
            + "        \"checkPattern\":\"\",\n" + "        \"paramLength\":\"20\",\n"
            + "        \"paramIsCheck\":\"1\",\n" + "        \"paramDirection\":\"0\",\n"
            + "        \"paramValueType\":\"String\",\n" + "        \"paramId\":\"23420269334897837100\",\n"
            + "        \"serviceId\":\"\",\n" + "        \"paramValue\":\"\"\n" + "    },\n" + "    {\n"
            + "        \"paramMappingKey\":\"\",\n" + "        \"paramOrder\":\"2\",\n"
            + "        \"isEncode\":\"0\",\n" + "        \"paramParentId\":\"\",\n"
            + "        \"checkRule\":\"NotEmpty\",\n" + "        \"paramCName\":\"用户组\",\n"
            + "        \"paramPosition\":\"0\",\n" + "        \"paramName\":\"userList\",\n"
            + "        \"paramEncode\":\"\",\n" + "        \"paramIndex\":\"\",\n" + "        \"paramType\":\"1\",\n"
            + "        \"paramDesc\":\"\",\n" + "        \"encodeMappingKey\":\"userListRel\",\n"
            + "        \"checkPattern\":\"\",\n" + "        \"paramLength\":\"\",\n"
            + "        \"paramIsCheck\":\"1\",\n" + "        \"paramDirection\":\"0\",\n"
            + "        \"paramValueType\":\"list\",\n" + "        \"paramId\":\"23420269344115450168\",\n"
            + "        \"serviceId\":\"\",\n" + "        \"paramValue\":\"\",\n" + "        \"formList\":[\n"
            + "            {\n" + "                \"paramMappingKey\":\"\",\n"
            + "                \"paramOrder\":\"2.1\",\n" + "                \"isEncode\":\"0\",\n"
            + "                \"paramParentId\":\"2\",\n" + "                \"checkRule\":\"\",\n"
            + "                \"paramCName\":\"年龄\",\n" + "                \"paramPosition\":\"0\",\n"
            + "                \"paramName\":\"age\",\n" + "                \"paramEncode\":\"\",\n"
            + "                \"paramIndex\":\"\",\n" + "                \"paramType\":\"0\",\n"
            + "                \"paramDesc\":\"\",\n" + "                \"encodeMappingKey\":\"\",\n"
            + "                \"checkPattern\":\"\",\n" + "                \"paramLength\":\"20\",\n"
            + "                \"paramIsCheck\":\"0\",\n" + "                \"paramDirection\":\"0\",\n"
            + "                \"paramValueType\":\"String\",\n"
            + "                \"paramId\":\"23420269353633932101\",\n" + "                \"serviceId\":\"\",\n"
            + "                \"paramValue\":\"\"\n" + "            }\n" + "        ]\n" + "    },\n" + "    {\n"
            + "        \"paramMappingKey\":\"\",\n" + "        \"paramOrder\":\"1\",\n"
            + "        \"isEncode\":\"0\",\n" + "        \"paramParentId\":\"\",\n" + "        \"checkRule\":\"\",\n"
            + "        \"paramCName\":\"支付标识\",\n" + "        \"paramPosition\":\"0\",\n"
            + "        \"paramName\":\"flag\",\n" + "        \"paramEncode\":\"1\",\n"
            + "        \"paramIndex\":\"\",\n" + "        \"paramType\":\"0\",\n"
            + "        \"paramDesc\":\"1-成功，0-失败\",\n" + "        \"encodeMappingKey\":\"\",\n"
            + "        \"checkPattern\":\"\",\n" + "        \"paramLength\":\"1\",\n"
            + "        \"paramIsCheck\":\"0\",\n" + "        \"paramDirection\":\"1\",\n"
            + "        \"paramValueType\":\"String\",\n" + "        \"paramId\":\"23420269362590224156\",\n"
            + "        \"serviceId\":\"\",\n" + "        \"paramValue\":\"\"\n" + "    },\n" + "    {\n"
            + "        \"paramMappingKey\":\"\",\n" + "        \"paramOrder\":\"2\",\n"
            + "        \"isEncode\":\"0\",\n" + "        \"paramParentId\":\"\",\n"
            + "        \"checkRule\":\"NotEmpty\",\n" + "        \"paramCName\":\"用户组\",\n"
            + "        \"paramPosition\":\"0\",\n" + "        \"paramName\":\"userOutList\",\n"
            + "        \"paramEncode\":\"\",\n" + "        \"paramIndex\":\"\",\n" + "        \"paramType\":\"1\",\n"
            + "        \"paramDesc\":\"\",\n" + "        \"encodeMappingKey\":\"userOutLIstRel\",\n"
            + "        \"checkPattern\":\"\",\n" + "        \"paramLength\":\"\",\n"
            + "        \"paramIsCheck\":\"1\",\n" + "        \"paramDirection\":\"1\",\n"
            + "        \"paramValueType\":\"List\",\n" + "        \"paramId\":\"23420269371696773137\",\n"
            + "        \"serviceId\":\"\",\n" + "        \"paramValue\":\"\",\n" + "        \"formList\":[\n"
            + "            {\n" + "                \"paramMappingKey\":\"\",\n"
            + "                \"paramOrder\":\"2.1\",\n" + "                \"isEncode\":\"0\",\n"
            + "                \"paramParentId\":\"2\",\n" + "                \"checkRule\":\"\",\n"
            + "                \"paramCName\":\"用户Id\",\n" + "                \"paramPosition\":\"0\",\n"
            + "                \"paramName\":\"id\",\n" + "                \"paramEncode\":\"\",\n"
            + "                \"paramIndex\":\"\",\n" + "                \"paramType\":\"0\",\n"
            + "                \"paramDesc\":\"\",\n" + "                \"encodeMappingKey\":\"\",\n"
            + "                \"checkPattern\":\"\",\n" + "                \"paramLength\":\"\",\n"
            + "                \"paramIsCheck\":\"0\",\n" + "                \"paramDirection\":\"1\",\n"
            + "                \"paramValueType\":\"String\",\n"
            + "                \"paramId\":\"23420269381569239104\",\n" + "                \"serviceId\":\"\",\n"
            + "                \"paramValue\":\"\"\n" + "            }\n" + "        ]\n" + "    }\n" + "]";
        // body里的字段解密
        return JSON.parseArray(s, ValidatorForm.class);
    }

    public static void main(String[] args) {
        RequestMessageTool cipherFilter = new RequestMessageTool();
        Map<String, Object> map = null;
        String s =
            "{\"username\": \"11\",\"userList\":[{\"user1\":\"1\",\"age\":\"1\"},{\"user1\":\"2\",\"age\":\"2\"},{\"user1\":\"3\",\"age\":\"3\"},{\"user1\":\"2\",\"age\":\"2\"},{\"user1\":\"3\",\"age\":\"3\"}]}";
        try {
            map = cipherFilter.packRequestMessage("", cipherFilter.getValidatorList(), JSONObject.fromObject(s));
        } catch (Exception e) {
            e.printStackTrace();
        }

        String sq = "11";
    }
}
